#include <windows.h>
#include <commctrl.h>
#include <fstream>
#include <filesystem>
#include "YunUtility.hpp"
#include "MainWindow.hpp"
#include "Color.hpp"
#include <nlohmann/json.hpp>

// 定义控件ID
#define ID_SUBMIT_BUTTON 2000
#define ID_BACK_BUTTON 2001
#define ID_TIMER 2100

using json = nlohmann::json;

// 全局变量定义
// -- 游戏窗口属性
int width = 1000;
int width_center = width / 2;
int height = 600;
int height_center = height / 2;
// -- 卡牌属性
int CardWidth = 80;
int CardHeight = 160;
int CardGap = 10;
// -- 当前选中的卡牌索引（-1表示没有选中）
int SelectedCardIndex = -1;
// -- 第一次点击的卡牌索引（用于交换，-1表示没有第一次点击）
int FirstClickIndex = -1;
// -- 游戏窗口标签
HWND CorrectCountLabel;
HWND TimerLabel;
/*<-*/ int TimerCount = 0;
/*<-*/ const int TimeLimit = 1000;
HWND OperationsLabel;
// -- 其他计数器
int OperationsCount = 0;         // 操作计数器
const int OperationsLimit = 500; // 操作限制

// 游戏窗口的窗口过程函数
LRESULT CALLBACK GameWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    // 处理游戏逻辑
    switch (uMsg) {
    case WM_CREATE: {
        // 初始化游戏窗口
        // -- 设置图标
        LoadAppIcon(hWnd);
        // -- 获取窗口大小
        RECT rect;
        GetClientRect(hWnd, &rect);
        width = rect.right - rect.left;
        width_center = width / 2;
        height = rect.bottom - rect.top;
        height_center = height / 2;
        // -- 创建提交按钮
        HWND SubmitButton = CreateWindowEx(
            0,
            L"BUTTON",
            L"提交",
            WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
            GetCenterWidth(width, 200),
            height_center + 100 /*自定义下偏移量*/,
            200,
            60,
            hWnd,
            (HMENU)ID_SUBMIT_BUTTON,
            hInst,
            NULL);
        // <- 设置按钮字体
        SendMessage(SubmitButton, WM_SETFONT, (WPARAM)CreateFontSize(24), TRUE);
        // -- 创建显示正确个数的标签
        CorrectCountLabel = CreateWindowEx(
            0,
            L"STATIC",
            L"正确个数：-",
            WS_CHILD | WS_VISIBLE | SS_CENTER,
            GetCenterWidth(width, 200) + 50 /*自定义右偏移量*/,
            height_center - 200 /*自定义上偏移量*/,
            90,
            30,
            hWnd,
            NULL,
            hInst,
            NULL);
        // <- 设置标签字体
        SendMessage(CorrectCountLabel, WM_SETFONT, (WPARAM)CreateFontSize(20), TRUE);
        // -- 创建返回按钮
        HWND BackButton = CreateWindowEx(
            0,
            L"BUTTON",
            L"返回",
            WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
            width - 50 /*按钮宽度*/ - 10 /*自定义左偏移量*/,
            0 + 10 /*间隙*/,
            50,
            30,
            hWnd,
            (HMENU)ID_BACK_BUTTON,
            hInst,
            NULL);
        // <- 设置按钮字体
        SendMessage(BackButton, WM_SETFONT, (WPARAM)CreateFontSize(20), TRUE);
        // -- 创建计时器标签
        TimerLabel = CreateWindowEx(
            0,
            L"STATIC",
            L"用时：0秒",
            WS_CHILD | WS_VISIBLE | SS_CENTER,
            width - 90 /*标签宽度*/ - 10 /*自定义左偏移量*/,
            0 + 10 /*间隙*/ + 30 /*上文按钮高度*/ + 10 /*自定义间隙*/,
            90,
            30,
            hWnd,
            NULL,
            hInst,
            NULL);
        // <- 设置标签字体
        SendMessage(TimerLabel, WM_SETFONT, (WPARAM)CreateFontSize(20), TRUE);
        TimerCount = 0; // 初始化计时器计数器
        // <- 创建对应的计时器
        SetTimer(hWnd, ID_TIMER, 1000, NULL);
        // -- 创建操作标签
        OperationsLabel = CreateWindowEx(
            0,
            L"STATIC",
            L"操作次数：0次",
            WS_CHILD | WS_VISIBLE | SS_CENTER,
            width - 120 /*标签宽度*/ - 10 /*自定义左偏移量*/,
            0 + 80 /*所有自定义高度*/,
            120,
            30,
            hWnd,
            NULL,
            hInst,
            NULL);
        // <- 设置标签字体
        SendMessage(OperationsLabel, WM_SETFONT, (WPARAM)CreateFontSize(20), TRUE);
        OperationsCount = 0; // 初始化操作计数器
        break;
    }
    case WM_PAINT: {
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hWnd, &ps);

        // 设置透明背景
        SetBkMode(hdc, TRANSPARENT);

        int StartingDrawingPositionX = GetCenterWidth(width, CardCount * CardWidth + (CardCount - 1) * CardGap);
        int StartingDrawingPositionY = 150;

        for (int i = 0; i < CardCount; i++) {
            CardsAttributes color = InitialCardsColor[i];
            int x = StartingDrawingPositionX + i * (CardWidth + CardGap);
            int y = StartingDrawingPositionY;

            // 创建画刷
            HBRUSH hBrush = CreateSolidBrush(RGB(color.r, color.g, color.b));
            HBRUSH hOldBrush = (HBRUSH)SelectObject(hdc, hBrush);

            // 创建圆角矩形
            int cornerRadius = 15; // 圆角半径
            RoundRect(hdc, x, y, x + CardWidth, y + CardHeight, cornerRadius, cornerRadius);

            // 恢复旧画刷并删除新画刷
            SelectObject(hdc, hOldBrush);
            DeleteObject(hBrush);

            // 如果这是选中的卡牌，添加描边
            if (i == SelectedCardIndex) {
                // 创建红色描边画笔
                HPEN hPen = CreatePen(PS_SOLID, 3, RGB(255, 0, 0)); // 3像素宽的红色描边
                HPEN hOldPen = (HPEN)SelectObject(hdc, hPen);

                // 创建空画刷（只绘制边框）
                HBRUSH hNullBrush = (HBRUSH)GetStockObject(NULL_BRUSH);
                HBRUSH hOldBrush2 = (HBRUSH)SelectObject(hdc, hNullBrush);

                // 绘制描边矩形（比卡牌稍大）
                int borderOffset = 2; // 描边偏移量
                RoundRect(hdc,
                          x - borderOffset, y - borderOffset,
                          x + CardWidth + borderOffset, y + CardHeight + borderOffset,
                          cornerRadius + 2, cornerRadius + 2);

                // 恢复旧画笔和画刷
                SelectObject(hdc, hOldPen);
                SelectObject(hdc, hOldBrush2);
                DeleteObject(hPen);
            }
        }

        // 创建字体
        HFONT hFont20 = CreateFontSize(20);

        // 设置文本颜色和背景
        SetTextColor(hdc, RGB(0, 0, 0)); // 黑色文本
        SetBkMode(hdc, TRANSPARENT);     // 透明背景

        // 选择字体到设备上下文
        HFONT hOldFont20 = (HFONT)SelectObject(hdc, hFont20);
        // 绘制文本（窗口主标题）
        RECT MainWindowTitleRect = {10, 10, st_mwa.width_center, 30};
        DrawText(hdc, Username.c_str(), -1, &MainWindowTitleRect,
                 DT_LEFT | DT_TOP | DT_SINGLELINE);
        SelectObject(hdc, hOldFont20); // 恢复原字体

        // 删除新字体
        DeleteObject(hFont20);

        EndPaint(hWnd, &ps);
        break;
    }
    case WM_LBUTTONDOWN: {
        // 获取鼠标点击坐标
        int mouseX = LOWORD(lParam);
        int mouseY = HIWORD(lParam);

        int StartingDrawingPositionX = GetCenterWidth(1000, CardCount * CardWidth + (CardCount - 1) * CardGap);
        int StartingDrawingPositionY = 150;

        // 遍历所有卡牌，检测点击
        for (int i = 0; i < CardCount; i++) {
            int x = StartingDrawingPositionX + i * (CardWidth + CardGap);
            int y = StartingDrawingPositionY;

            // 检查鼠标是否在卡牌矩形区域内
            if (mouseX >= x && mouseX <= x + CardWidth && mouseY >= y && mouseY <= y + CardHeight) {
                // 卡牌交换逻辑
                if (FirstClickIndex == -1) {
                    // 第一次点击：记录卡牌索引并显示描边
                    FirstClickIndex = i;
                    SelectedCardIndex = i;
                } else {
                    // 第二次点击：执行交换操作
                    if (FirstClickIndex != i) { // 确保不是点击同一张卡牌
                        // 交换整个CardsAttributes结构体（包括颜色和id）
                        CardsAttributes tempCard = InitialCardsColor[FirstClickIndex];
                        InitialCardsColor[FirstClickIndex] = InitialCardsColor[i];
                        InitialCardsColor[i] = tempCard;

                        // -- 判断是否超过操作次数限制
                        if (OperationsCount >= OperationsLimit) {
                            // 超过，显示提示
                            MessageBox(hWnd, L"超出操作限制，游戏结束", L"提示", MB_OK | MB_ICONINFORMATION);
                            // 销毁当前游戏窗口
                            DestroyWindow(hWnd);
                            ShowWindow(::hWnd, SW_SHOW);
                        }
                        // 更新操作计数
                        OperationsCount++;
                        // 更新操作标签
                        wchar_t operationsText[20];
                        swprintf_s(operationsText, L"操作次数：%d次", OperationsCount);
                        SetWindowText(OperationsLabel, operationsText);
                    }

                    // 重置第一次点击索引，准备下一次交换
                    FirstClickIndex = -1;
                    SelectedCardIndex = -1;
                }

                // 触发重绘，更新显示
                InvalidateRect(hWnd, NULL, TRUE);
                UpdateWindow(hWnd);

                break;
            }
        }
        break;
    }
    case WM_COMMAND: {
        switch (LOWORD(wParam)) {
        case ID_SUBMIT_BUTTON: {
            // 检查正确个数
            int correctCount = 0;
            for (int i = 0; i < CardCount; i++) {
                // 比较对应位置的id是否匹配
                if (InitialCardsColor[i].id == TargetCardsColor[i].id) {
                    correctCount++;
                }
            }
            // 更新正确个数标签
            wchar_t correctCountText[10];
            swprintf_s(correctCountText, L"正确个数：%d", correctCount);
            SetWindowText(CorrectCountLabel, correctCountText);
            // 如果正确个数等于卡牌数量，显示提示
            if (correctCount == CardCount) {
                auto &wtu = wstring_to_utf8;
                std::string strUsr = wtu(Username);
                std::string strCardC = std::to_string(CardCount);
                // 确保GameData是一个对象
                    if (!GameData.is_object()) {
                        GameData = nlohmann::json::object();
                    }
                    
                    // 确保卡牌数量键存在并且是一个对象
                    if (!GameData.contains(strCardC) || !GameData[strCardC].is_object()) {
                        GameData[strCardC] = nlohmann::json::object();
                    }
                    
                    if (!GameData[strCardC].contains(strUsr) || !GameData[strCardC][strUsr].is_object()) {
                        // 新用户，直接设置初始值
                        GameData[strCardC][strUsr]["AverageDuration"] = TimerCount;
                        GameData[strCardC][strUsr]["AverageOperationsCount"] = OperationsCount;
                    } else {
                        // 已有用户，计算平均值
                        auto &userNode = GameData[strCardC][strUsr];
                        userNode["AverageDuration"] = std::round(((userNode.value("AverageDuration", TimerCount) + TimerCount) / 2.0) * 100) / 100;
                        userNode["AverageOperationsCount"] = std::round(((userNode.value("AverageOperationsCount", OperationsCount) + OperationsCount) / 2.0) * 100) / 100;
                    }
                    
                    // 保存到文件
                    std::filesystem::create_directories("config");
                    std::ofstream out("config/GameData.json", std::ios::out);
                    out << GameData.dump(4);
                    out.close();
                // 销毁当前游戏窗口
                DestroyWindow(hWnd);
                // 使用PostMessage延迟显示消息框，避免阻塞窗口销毁
                PostMessage(::hWnd, WM_USER + 100, 0, 0);
            } else {
                // 如果不是全部正确，只更新正确个数标签，不销毁窗口
                // 这样就不会触发WM_DESTROY显示主窗口
            }
            break;
        }
        case ID_BACK_BUTTON: {
            // 提示是否返回主窗口
            if (MessageBox(hWnd, L"是否返回主窗口？", L"提示", MB_YESNO | MB_ICONQUESTION) == IDYES) {
                // 销毁当前游戏窗口
                DestroyWindow(hWnd);
                // 显示主窗口
                ShowWindow(::hWnd, SW_SHOW);
            }
            break;
        }
        }
        break;
    }
    case WM_TIMER: {
        // 判断是否超时
        if (TimerCount >= TimeLimit) {
            // 停止计时器
            KillTimer(hWnd, ID_TIMER);
            // 超时，显示提示
            MessageBox(hWnd, L"时间到，游戏结束", L"提示", MB_OK | MB_ICONINFORMATION);
            // 销毁当前游戏窗口
            DestroyWindow(hWnd);
            ShowWindow(::hWnd, SW_SHOW);
        }
        // 更新计时器计数
        TimerCount++;
        // 更新计时器标签
        wchar_t timerText[20];
        swprintf_s(timerText, L"用时：%d秒", TimerCount);
        SetWindowText(TimerLabel, timerText);
        break;
    }
    case WM_CLOSE: {
        // 提示是否返回主窗口
        if (MessageBox(hWnd, L"是否关闭正在进行的游戏？\n进度将不会保存", L"提示", MB_YESNO | MB_ICONQUESTION) == IDYES) {
            // 显示主窗口
            ShowWindow(::hWnd, SW_SHOW);
            DestroyWindow(hWnd); // 销毁当前窗口
        } else {
            // 用户选择"否"，不执行任何操作（窗口保持打开）
            return 0;
        }
        break;
    }
    case WM_DESTROY:
        KillTimer(hWnd, ID_TIMER); // 销毁计时器
        GameWindow = NULL;         // 设置游戏窗口句柄为空
        // 只有在游戏胜利时才显示主窗口
        // 其他情况下（如用户手动关闭）不显示主窗口
        return 0;
    default:
        return DefWindowProc(hWnd, uMsg, wParam, lParam);
    }
    return 0;
}